﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace EvoSim.Simulation
{
	public class Entity
	{
		public string EntityName;
		public World World;

		Point _region;
		public Point Region
		{
			get { return _region; }
			set
			{
				World.Regions[Region.X, Region.Y].Remove(this);
				World.Regions[value.X, value.Y].Add(this);

				_region = value;
			}
		}

		double rotation;
		public double Rotation
		{
			get { return rotation; }
			set
			{
				rotation = value;

				if (rotation < 0)
					rotation = Math.PI * 2 + rotation;
				else if (rotation > Math.PI * 2)
					rotation = rotation - Math.PI * 2;
			}
		}

		EntityPosition _position;
		public EntityPosition Position
		{
			get { return _position; }
			set
			{
				_position = value;

				if (World.WorldHasEdges)
				{
					if (_position.X < 0)
						_position.X = 0;
					else if (_position.X >= World.Width)
						_position.X = World.Width - 1;

					if (_position.Y < 0)
						_position.Y = 0;
					else if (_position.Y >= World.Height)
						_position.Y = World.Height - 1;
				}
				else
				{
					if (_position.X < 0)
						_position.X = World.Width + _position.X;
					else if (_position.X > World.Width)
						_position.X = _position.X - World.Width;

					if (_position.Y < 0)
						_position.Y = (World.Height - 1) + _position.Y;
					else if (_position.Y >= World.Height)
						_position.Y = _position.Y - World.Height;
				}

				var region = GetRegionPoint(Position.X, Position.Y);

				if (region.X != Region.X || region.Y != Region.Y)
					Region = region;
			}
		}
		public void Move(double dx, double dy)
		{
			var newPos = Position;
			newPos.X += dx;
			newPos.Y += dy;

			Position = newPos;
		}

		public void CheckRegion()
		{
			DeleteFromRegion();

			_region.X = (int)Math.Round(_position.X / World.RegionSize, 0);
			_region.Y = (int)Math.Round(_position.Y / World.RegionSize, 0);

			World.Regions[Region.X, Region.Y].Add(this);
		}
		public void DeleteFromRegion()
		{
			for (int x = 0; x < World.RegionLengthX; x++)
			{
				for (int y = 0; y < World.RegionLengthY; y++)
				{
					if (World.Regions[x, y].Contains(this))
						World.Regions[x, y].Remove(this);
				}
			}
		}

		public Point GetRegionPoint(double x, double y)
		{
			var regionPoint = new Point();
			regionPoint.X = (int)(_position.X / World.RegionSize);
			regionPoint.Y = (int)(_position.Y / World.RegionSize);

			return regionPoint;
		}

		public Color EntityColor;
		public virtual int Radius { get; set; }
		public int Age;

		public bool IsDead { get; private set; }

		public Entity(string name)
		{
			EntityName = name;
		}

		public virtual void Update(GameTime gameTime)
		{
			Age += 1;
		}

		public void Kill()
		{
			IsDead = true;
		}
	}

	public struct EntityPosition
	{
		public double X;
		public double Y;

		public EntityPosition(double x, double y)
		{
			X = x;
			Y = y;
		}
	}
}
